package cgl.narada.samples.security;

/**
 * This class is adapted from cgl.narada.samples.rtp.NBRTPReceiver.
 * It uses NBMediaConnector to receive stream.
 *
 * @author Hasan Bulut  - hbulut@indiana.edu
 * Community Grids Lab., Indiana University
 * @version 1.0
 */
import java.util.Properties;

import javax.media.protocol.DataSource;
import javax.media.rtp.Participant;
import javax.media.rtp.RTPConnector;
import javax.media.rtp.RTPControl;
import javax.media.rtp.RTPManager;
import javax.media.rtp.ReceiveStream;
import javax.media.rtp.ReceiveStreamListener;
import javax.media.rtp.event.ByeEvent;
import javax.media.rtp.event.NewReceiveStreamEvent;
import javax.media.rtp.event.ReceiveStreamEvent;
import javax.media.rtp.event.RemotePayloadChangeEvent;
import javax.media.rtp.event.StreamMappedEvent;
import javax.media.rtp.event.TimeoutEvent;

import cgl.narada.samples.rtp.PlayerWindow;
import cgl.narada.service.ServiceException;

public class NBMediaReceiver implements ReceiveStreamListener {

    private RTPManager rtpManager;
    private RTPConnector connector;

    public NBMediaReceiver(RTPConnector connector) {
        this.connector = connector;
    }

    public PlayerWindow playerWindow;

    public String initialize() {
        try {
            rtpManager = (RTPManager) RTPManager.newInstance();
            rtpManager.addReceiveStreamListener(this);
            rtpManager.initialize(connector);

        } catch (Exception e) {
            e.printStackTrace();
            return "Cannot create the RTP Session: " + e.getMessage();
        }

        return null;
    }

    public void close() {

        if (rtpManager != null) {
            rtpManager.removeTargets("Closing session.");
            rtpManager.dispose();
            rtpManager = null;
        }
    }

    public synchronized void update(ReceiveStreamEvent evt) {

        Participant participant = evt.getParticipant();
        ReceiveStream stream = evt.getReceiveStream();
        if (evt instanceof RemotePayloadChangeEvent) {
            System.err
                    .println("Received an RTP PayloadChangeEvent. Does nothing.");
        } else if (evt instanceof NewReceiveStreamEvent) {
            try {
                stream = ((NewReceiveStreamEvent) evt).getReceiveStream();
                DataSource ds = stream.getDataSource();

                playerWindow = new PlayerWindow(ds);
                // Find out the formats.
                RTPControl ctl = (RTPControl) ds
                        .getControl("javax.media.rtp.RTPControl");
                if (ctl != null) {
                    System.err
                            .println("---- Recevied new RTP stream. Format is "
                                    + ctl.getFormat() + "  ssrc: "
                                    + stream.getSSRC());
                } else {
                    System.err
                            .println("---- Recevied new RTP stream. Format is not known yet. ssrc: "
                                    + stream.getSSRC());
                }
            } catch (Exception e) {
                System.err.println("NewReceiveStreamEvent exception "
                        + e.getMessage());
                e.printStackTrace();
                return;
            }
        } else if (evt instanceof StreamMappedEvent) {
            // Find out the formats.
            /*
             * RTPControl ctl = (RTPControl) stream.getDataSource().getControl(
             * "javax.media.rtp.RTPControl"); if (ctl != null)
             * System.err.println("---- The previously unidentified stream is " +
             * ctl.getFormat());
             */
        } else if (evt instanceof ByeEvent) {
            if (participant != null) {
                System.err.println("  - Got \"bye\" from: "
                        + participant.getCNAME()
                        + "This rtp session is closed.");
            }
        } else if (evt instanceof TimeoutEvent) {
            if (participant != null) {
                System.err.println("  - timeout occured for: "
                        + participant.getCNAME());
            } else {
                System.out.println("  - timeout occured");
            }
        }
    }

    public static void startReceiver(NBMediaConnector connector) {
        NBMediaReceiver cr = new NBMediaReceiver(connector);
        String result = cr.initialize();
        if (result != null) {
            System.err
                    .println("Failed to initialize the session. The error message is: "
                            + result);
        } else {
            System.err.println("  - Waiting for video stream to arrive....");
        }
    }

    public static void main(String args[]) throws java.io.IOException {

        if ((args.length < 4) || (args.length > 5)) {
            printUsage();
            return;
        }
        String module = "NBMediaReceiver.main()->";

        String brokerIP = args[0];
        int brokerPort = Integer.parseInt(args[1]);
        int topicNumber = Integer.parseInt(args[2]);
        Properties props = new Properties();
        props.put("hostname", brokerIP);
        props.put("portnum", args[1]);
        String commType = args[3];
        String replayTopic = "ReplayTopic/Media/Data/" + topicNumber;
        String dataTopic = "Media/Data/" + topicNumber;
        NBMediaConnector connector = new NBMediaConnector(brokerIP, brokerPort,
                1, topicNumber);

        String control = connector.getControlTopic();
        String data = connector.getDataTopic();

        SecureTopicsKeyGenerator stkGen = new SecureTopicsKeyGenerator(data,
                control, "c2", brokerIP, "" + brokerPort, commType);
        stkGen.genTopicsAndKeys();

        try {
            connector.initializeBrokerCommunications(props, commType);
            connector.subscribe(stkGen.topicUUIDData, stkGen.stkData, stkGen.rootCA);
            connector.initializeTransmitter(null, null, null, stkGen.topicUUIDData,
                    stkGen.stkData, stkGen.topicUUIDControl, stkGen.stkControl,
                    stkGen.c_priv);

        } catch (ServiceException ex) {
            ex.printStackTrace();
        }
        startReceiver(connector);

        // wait here
        while (true) {
            try {
                Thread.sleep(10000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void printUsage() {
        System.out
                .println("java cgl.narada.samples.rtp.Receiver <Broker IP> <Broker Port> <Topic Number>");
    }

} // end of Receiver
